package com.ihealthway.all.groupbuy.services;

import com.ihealthway.all.utils.Utils;
import com.ihealthway.all.groupbuy.vo.AdminLog;
import com.ihealthway.all.task.AsyncOperateLogTask;
import org.nutz.dao.Cnd;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlCallback;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * admin operate log service
 * @author 凡梦星尘(elkan1788@gmail.com)
 */
@IocBean(fields = { "dao" })
public class AdminLogService extends BaseService<AdminLog> {

    private static final Log logger = Logs.get();

    public void asyncLog(AdminLog operateLog) {

        try {
            boolean result = AsyncOperateLogTask.LOGS_QUEUE
                    .offer(operateLog, 100, TimeUnit.MILLISECONDS);
            if (!result) {
               logger.errorf("Offer operate log object into queue failed: %s", operateLog);
            }
        } catch (InterruptedException e) {
            logger.error("Async admin operate log into queue failed.", e);
        }

    }

    public Map<String, Object> getAdminLogData(int page, int rows, String moduleName, String operateType,
                                               String logContent, String startDate, String endDate) {

        Criteria cri = Cnd.cri();

        if (Strings.isNotBlank(moduleName) && !Strings.equalsIgnoreCase(moduleName, "-1")) {
            cri.where().and("log.module", "=", moduleName);
        }

        if (Strings.isNotBlank(operateType) && !Strings.equalsIgnoreCase(operateType, "-1")) {
            cri.where().and("log.operate_type", "=", operateType);
        }

        if (Strings.isNotBlank(logContent)) {
            cri.where().andLike("log.content", logContent, true);
        }

        if (Strings.isNotBlank(startDate) && Strings.isNotBlank(endDate)) {
            cri.where().andBetween("log.create_time", startDate+" 00:00:00", endDate+" 23:59:59");
        }

        cri.getOrderBy().desc("log.create_time");

        String sqlStmt = "SELECT log.*, admin.nick_name AS nickName FROM gb_admin_operatelog log LEFT JOIN gb_sysadmin admin ON log.sa_id = admin.sa_id $condition";


        Map<String, Object> data = new HashMap<>();
        try {
            data.putAll(easyuiDGPagerWithFetch(sqlStmt, page, rows, cri, new AdminLogPagerCallback()));
        } catch (Exception e) {
            logger.error("Find admin operate log grid data failed.", e);
        }

        return data;
    }

    private class AdminLogPagerCallback implements SqlCallback {

        private List<AdminLog> adminLogs = new ArrayList<>();

        @Override
        public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {

            while (rs.next()) {
                AdminLog adminLog = getEntity().getObject(rs, null, "log.");
                String nickName = rs.getString("nickName");
                adminLog.setNickName(nickName);

                adminLog.setModule(Utils.replaceLogModuleName(adminLog.getModule()));
                adminLog.setOperateType(Utils.replaceLogOperateType(adminLog.getOperateType()));

                adminLogs.add(adminLog);
            }

            return adminLogs;
        }
    }
}
